<?php 
/**
* @author  Oliver Leisalu, Inditel Meedia
* @package DomXml
*/
class DomXmlNode {
	/**
	 * Tag name
	 * @var String
	 */
	protected $name;
	/**
	 * @var String
	 */
	protected $namespace;
	/**
	 * Parent node
	 * @var DomXmlNode
	 */
	protected $parent;
	/**
	 * Attributes array. Key value pairs.
	 * @var Array
	 */
	protected $attributes = array();
	/**
	 * Children
	 * @var DomXmlNode[]
	 */
	protected $childNodes = array();
	/**
	 * Tag contents
	 * @var String
	 */
	protected $value;
	

	/**
	 * @param String $name
	 */
	public function __construct( $name ) {
		$this->setName( $name );
	}
	


	/**
	 * @param DomXmlNode $node
	 */
	public function addChildNode( DomXmlNode $node ) {
		$this->childNodes[] = $node;
		$node->setParentNode( $this );
	}
	/**
	 * @param DomXmlNode $node
	 */
	private function setParentNode( DomXmlNode $node ) {
		$this->parent = $node;
	}
	/**
	 * @param array $attributes
	 */
	public function setAttributes( array $attributes = array() ) {
		foreach( $attributes as $key => $value )
			$this->setAttribute( $key, $value);
	}
	/**
	 * @param String $key
	 * @param String $value
	 */
	public function setAttribute( $key, $value ) {
		$this->attributes[$key] = $value;
	}
	/**
	 * @param String $value
	 */
	public function setValue( $value ) {
		$this->value = $value;
	}
	/**
	 * @param String $value
	 */
	public function addValue( $value ) {
		$this->value .= $value;
	}
	/**
	 * @param String $namespace
	 */
	public function setNamespace( $namespace ) {
		$this->namespace = $namespace;
	}
	/**
	 * @param String $namespace
	 */
	public function setName( $name ) {
		$this->name = $name;
	}
	
	/**
	 * @return Mixed
	 */
	public function __get( $var ) {
		return $this->$var;
	}
	/**
	 * @return DomXmlNode
	 */
	public function getNode( $i ) {
		return $this->childNodes[$i] ? $this->childNodes[$i] : new DomXmlNotExistingNode($this,'getNode('.$i.')');
	}
	/**
	 * @return DomXmlNode
	 */
	public function getFirstNode() {
		return $this->childNodes[0] ? $this->childNodes[0] : new DomXmlNotExistingNode($this,'getFirstNode()');
	}
	/**
	 * @return DomXmlNode
	 */
	public function getLastNode() {
		$n = count($this->childNodes)-1;
		return $this->childNodes[$n] ? $this->childNodes[$n] : new DomXmlNotExistingNode($this,'getFirstNode()');
	}
	
	/**
	 * Return parents next node
	 * @return DomXmlNode
	 */
	public function getNextSibling() {
		if( !$this->parent )
			return new DomXmlNotExistingNode($this,'getNextSibling()');
		
		return $this->parent->getNext( $this );
	}
	/**
	 * Return parents previous node
	 * @return DomXmlNode
	 */
	public function getPrevSibling() {
		if( !$this->parent )
			return new DomXmlNotExistingNode($this,'getPrevSibling()');
		
		return $this->parent->getPrev( $this );
	}
	/**
	 * Returns next node from given node
	 * @param DomXmlNode $node
	 * @return DomXmlNode
	 */
	public function getNext( DomXmlNode $node ) {
		$fnode = null;
		foreach( $this->childNodes as $k => $n ) {
			if( spl_object_hash($n) === spl_object_hash($node) ) {
				$fnode = $this->childNodes[$k+1];
				break;
			}
		}
		if( $fnode )
			return $fnode;
		else
			return new DomXmlNotExistingNode($this,'getNext('.$node->name.')' );
	}
	/**
	 * Returns previous node from given node
	 * @param DomXmlNode $node
	 * @return DomXmlNode
	 */
	public function getPrev( DomXmlNode $node ) {
		$fnode = null;
		foreach( $this->childNodes as $k => $n ) {
			if( spl_object_hash($n) === spl_object_hash($node) ) {
				$fnode = $this->childNodes[$k-1];
				break;
			}
		}
		if( $fnode )
			return $fnode;
		else
			return new DomXmlNotExistingNode($this,'getPrev('.$node->name.')' );
	}
	/**
	 * @param String $nodeName
	 * @param Bool $expec
	 * @return DomXmlNode
	 */
	public function getOneByNodeName( $nodeName ) {
		foreach( $this->childNodes as $node ) {
			if( $node->name == $nodeName )
				return $node;
		}
		return new DomXmlNotExistingNode($this,'getOneByNodeName('.$nodeName.')' );
	}
	/**
	 * @param String $nodeName
	 * @param Bool $expec
	 * @return DomXmlNode[]
	 */
	public function getByNodeName( $nodeName ) {
		$list = array();
		foreach( $this->childNodes as $node ) {
			if( $node->name == $nodeName )
				$list[] = $node;
		}
		return $list;
	}
	/**
	 * @return String
	 */
	public function __toString() {
		$name = ($this->namespace ? $this->namespace.':' : '').$this->name;
		$xml = '<'.$name.'';
		foreach( $this->attributes as $key => $attribute )
			$xml .= ' '.$key.'="'.$attribute.'"';
		$xml .= '>';
		
		$xml .= $this->value;
		
		foreach( $this->childNodes as $child )
			$xml .= $child->__toString();
		
		$xml .= '</'.$name.'>';
		return $xml;
	}
}
?>